GSoC23 — Workweek 2

Introduction

This week was a mix of maintenance work consisting of issue documentation and some minor pull requests. I also ran a few experiments that clarified how some things work in Icarus Verilog around specify and `celldefine. Let's take a look at it!

Maintenance Work

Although I had hoped to already devote myself to the INTERCONNECT feature, I was held up by other things:

I have created a tracking issue for SDF support in Icarus Verilog. The idea is to collect all open issues in one place to have a good overview what is still missing for good SDF support.

Talking about issues, I have opened some new ones too: #945, #946, #947, #949, #950

Some of these where obvious but not yet documented, and some issues like the TIMESCALE and the wildcard cell instantiation where not yet known I think.

I have also created two small PRs:

  • One to add a warning to indicate that TIMINGCHECK is currently unsupported: #944
  • And another one to warn that wildcard cell instantiations are not supported: #948

Funnily enough, wildcard cell instantiations would previously segfault due to null pointer access. So this is at least an improvement ;)

Project Focus

Now what do these issues mean for the project? Has the project focus shifted?

Not really, the foremost goal is still to implement the INTERCONNECT feature.

Another small issue that I was hit by was this one: #509

Port indices are not currently supported in an SDF file, and I have an example with SKY130 that uses them. (And any real world example will probably also hit this.)

To actually make use of the SDF simulation, Icarus Verilog eventually needs to support the TIMINGCHECK feature - at least for the timing checks used in the SKY130 PDK in combination with OpenROAD, i.e.: REMOVAL, RECOVERY, HOLD and SETUP. (This not the focus of this project, but would be nice to have.)

But a new issue has come up that I need to discuss in detail with my mentors: `celldefine

The `celldefine Problem

If we take a look at the Icarus Verilog regression suite, tests for SDF annotation often look like this:

module DFF (input D, input C, output reg Q);

   always @(posedge C)
     Q <= D;

   specify
      (posedge C => (Q +: D)) = (1,1);
   endspecify

endmodule

We have a module that is the target for annotation and we can already see, that a specify block defines the edge sensitive path delay from Q to D upon a rising edge of C.

The values (1,1) stand for (rise, fall) times.

The corresponding section in the SDF file looks like this:

 (CELL
    (CELLTYPE "DFF")
    (INSTANCE dut)
    (DELAY
     (ABSOLUTE
      (IOPATH (posedge C) Q (3.0:3.0:3.0) (3.0:3.0:3.0)) ) ) )
 )

And the SDF file is applied inside the testbench using $sdf_annotate("file.sdf");. This overwrites the values given in specify with the ones from the SDF file.

My misconception was to think that the specify block is only there to provide default values and so to prove that they are really overwritten. This is not true.

If one would remove the specify block Icarus Verilog will give an error along the lines:

SDF WARNING: top.v:29: Unable to match ModPath posedge C -> Q in tb.dut

The path was not found. This means Icarus Verilog relies on the specify block to tell it which paths can be potentially annotated via an SDF file.

Skywater PDK

The findings from before now can be used to understand the following issue.

Since the ultimate goal of this project is to simulate a design using the SKY130 PDK, I did some testing to make sure there aren't any other road blockers than thise described in Project Focus.

And as it seems there is another issue with annotating IOPATHs, which is a feature already supported in Icarus Verilog. When trying to annotate any cell, I get a similar SDF WARNING as stated above.

Maybe you already think what the issue could be: The cell module does not contain the path delays we are trying to annotate.

Let's have a look at a cell from the sky130_fd_sc_hd library, for example a simple flip-flop with inverted reset.

The sky130_fd_sc_hd__dfrtp_1 cell

In our final design the cell sky130_fd_sc_hd__dfrtp_1 is used, which looks like this:

`celldefine
module sky130_fd_sc_hd__dfrtp_1 (
    Q      ,
    CLK    ,
    D      ,
    RESET_B
);

    output Q      ;
    input  CLK    ;
    input  D      ;
    input  RESET_B;

    // Voltage supply signals
    supply1 VPWR;
    supply0 VGND;
    supply1 VPB ;
    supply0 VNB ;

    sky130_fd_sc_hd__dfrtp base (
        .Q(Q),
        .CLK(CLK),
        .D(D),
        .RESET_B(RESET_B)
    );

endmodule
`endcelldefine

For us interesting to note is the `celldefine directive, which I will talk about later in detail.

Well, standard cells are like an onion, we have to go one layer deeper. Here is the sky130_fd_sc_hd__dfrtp:

`celldefine
module sky130_fd_sc_hd__dfrtp (
    Q      ,
    CLK    ,
    D      ,
    RESET_B
);

    // Module ports
    output Q      ;
    input  CLK    ;
    input  D      ;
    input  RESET_B;

    // Local signals
    wire buf_Q;
    wire RESET;

    //                          Delay       Name  Output  Other arguments
    not                                     not0 (RESET , RESET_B        );
    sky130_fd_sc_hd__udp_dff$PR `UNIT_DELAY dff0 (buf_Q , D, CLK, RESET  );
    buf                                     buf0 (Q     , buf_Q          );

endmodule
`endcelldefine

This cell module only uses primitives, the smallest element that Verilog knows. These are simple logic gates like and and or, buffers and inverters like buf and not and many more. But what if there is no built-in primitive for your use-case? For example, there seem to be no primitives for flip-flops or latches. The solution is to use a UDP, User Defined Primitives, with which you can model any combinatorial or sequential logic that you could need.

And that's exactly what was done with the sky130_fd_sc_hd__udp_dff$PR (it even has udp in its name):

primitive sky130_fd_sc_hd__udp_dff$PR (
    Q    ,
    D    ,
    CLK  ,
    RESET
);

    output Q    ;
    input  D    ;
    input  CLK  ;
    input  RESET;

    reg Q;

    table
     //  D  CLK  RESET :  Qt : Qt+1
         *   b     0   :  ?  :  -    ; // data event, hold unless CP==x
         ?  (?0)   0   :  ?  :  -    ; // CP => 0, hold
         ?   b    (?0) :  ?  :  -    ; // R => 0, hold unless CP==x
         ?   ?     1   :  ?  :  0    ; // async reset
         0   r     ?   :  ?  :  0    ; // clock data on CP
         1   r     0   :  ?  :  1    ; // clock data on CP
         0  (x1)   ?   :  0  :  0    ; // possible CP, hold when D==Q==0
         1  (x1)   0   :  1  :  1    ; // possible CP, hold when D==Q==1
         0   x     ?   :  0  :  0    ; // unkown CP, hold when D==Q==0
         1   x     0   :  1  :  1    ; // unkown CP, hold when D==Q==1
         ?   b    (?x) :  0  :  0    ; // R=>x, hold when Q==0 unless CP==x
    endtable
endprimitive

The table describes its behavior depending on the inputs.

Okay, let's come back to our problem. Why can't Icarus Verilog annotate sky130_fd_sc_hd__dfrtp_1?

Well, do you see any specify blocks? And without any paths in specify blocks, Icarus Verilog won't add any paths that can be annotated from within an SDF file (or so it seems).

What does `celldefine do?

Let's come back to the `celldefine directive.

The standard says:

The directives `celldefine and `endcelldefine tag modules as cell modules. Cells are used by certain PLI routines for applications, such as delay calculations.

Okay, it does not specifically state anything about SDF, but I think it is used to tell the simulator, that any path inside the module (or rather cell module) may be annotated later on via, for example, an SDF file.

So it seems like Icarus Verilog does not currently support `celldefine and `endcelldefine and this is needed for at least the SKY130 PDK.

The alternative would be to add generate blocks to every cell in the PDK, but that does not sound very fun...

But it seems like exactly that was done for the CVC simulator, which seems to have the same restrictions as Icarus Verilog. Here, the sky130_fd_sc_hd standard cell library has been specifically modified to include specify blocks in all standard cells so that they can be annotated: sky130_fd_sc_hd for CVC.

These are currently just speculations on my part as I am waiting for comments from my mentors on this topic. So stay tuned for more information in the coming blog entries.

Summary

All in all, this means that there is one more issue to be added for SDF support on Icarus Verilog using SKY130 and OpenROAD. I hope that I have now found all issues that prevents Icarus Verilog from performing back-annotated gate level simulations using the SKY130 PDK.

Next week I will work less on this project as I prepare for the last two exams of this semester.

But afterwards, I will continue with full speed ahead!